#ifndef _LISTACOMPARTIDA_H_
#define _LISTACOMPARTIDA_H_

#include "Shm.h"
#include "Semaforo.h"
#include "log.h"

#include <vector>

template <class T> class ListaCompartida{
    Shm compartida;
    Semaforo semaforo;
    public:
    ListaCompartida(const char* path, int idLista):compartida(path,idLista),semaforo(path,idLista){
	log("########Se instancia la lista compartida con ID: %d\n", idLista);
    }

    std::vector<T> obtenerLista(){
	Lock l(semaforo);
	T* listaCompartida = (T *)compartida.getBase();
	int i=0;
	std::vector<T> lista;
	while(listaCompartida[i] != 0){
	    lista.push_back(listaCompartida[i]);
	    i++;
	}
	return lista;
    }

    int size(){
	return obtenerLista().size();
    }

    void eliminarElemento(T elemento){
	//log("#########elimino elemento %ld\n", elemento);
	Lock l(semaforo);
	T* listaCompartida = (T*)compartida.getBase();
	int ultimo=0;

	while(listaCompartida[ultimo+1] != 0)
	    ultimo++;

	int buscado = 0;
	while(listaCompartida[buscado] != elemento && buscado < ultimo)
	    buscado++;

	if(buscado <= ultimo){
	    listaCompartida[buscado] = listaCompartida[ultimo];
	    listaCompartida[ultimo] = 0;
	}
    }

    void mostrarElementos(){
	log("############Elementos:\n");
	long* listaCompartida = (long *)compartida.getBase();
	for(int i=0;i<10;i++){
	    log("Elemento %d: %ld\n", i, listaCompartida[i]);
	}
    }

    bool agregarElemento(T elemento){
	//log("################################Agrego elemento a la lista compartida %ld (base %d)\n", elemento, compartida.getBase());
	//mostrarElementos();
	Lock l(semaforo);
	long* listaCompartida = (long *)compartida.getBase();
	int i=0;
	while(listaCompartida[i] != 0){
	    if(listaCompartida[i] == elemento){
		log("##########agregarElemento: El elemento (%ld) ya existe (posicion %d).\n", elemento,i);
		return true;
	    }
	    i++;
	}
	//log("##########################Inserto al elemento en la posicion %d\n", i);
	listaCompartida[i] = elemento;
	listaCompartida[i+1] = 0;
	listaCompartida[i+2] = 0;
	return true;
    }

    void clear(){
	//log("####antes de borrar");
	//mostrarElementos();
	compartida.borrar();
	//log("####despues de borrar");
	//mostrarElementos();
    }

    ~ListaCompartida(){}
};

#endif /* _LISTACOMPARTIDA_H_ */
